package com.ww.scala.syntax

import java.util.Date

/**
 * 函数
 */
object syntax02_functions {

  def main(args: Array[String]): Unit = {


    def xxx(): Unit = {

    }

    // Unit = 可以不写
    def xxx1() {

    }

    //没有返回值
    def xxx31(): Unit = {
      3
    }

    //有返回值
    def xxx3(): Int = {
      3
    }

    var tmp = xxx3()
    println(tmp)

    //有return的时候,必须要有返回值
    def xxx4(): String = {
      return "xxx"
    }

    println("============参数============")

    //参数必须要指定类型
    //必须是val 修饰
    def xxx5(a: String): Unit = {

    }

    println("============递归============")

    //递归必须要指定函数的返回值类型
    def xxx6(a: Int): Int = {
      if (a == 1) {
        a
      } else {
        a * xxx6(a - 1)
      }
    }

    println(xxx6(3));
    println("============函数的默认值============")

    def xxx7(a: Int = 8, b: String = "xx"): Unit = {
      println(s"${a}-----$b")
    }

    xxx7(9)
    xxx7(b = "00")
    println("============匿名函数============")
    //注意函数类型的写法(函数签名)
    var y: (Int, Int) => Int = (a: Int, b: Int) => {
      a + b
    }
    var b = (a: Int, b: Int) => {
      a + b
    }
    println(y(1, 2))
    println(b(1, 2))

    println("============嵌套函数============")

    //xxx9 可以直接用xxx8 的参数
    def xxx8(a: Int): Unit = {
      def xxx9(): Unit = {
        println(a)
      }

      xxx9()
    }

    xxx8(9999)
    println("============偏应用函数============")

    def xxx10(date: Date, level: String, msg: String): Unit = {
      println(s"$date $level $msg")
    }

    xxx10(new Date(), "info", "ok")

    var log = xxx10(_: Date, "debug", _: String)

    log(new Date(), "xxx")
    println("============可变参数============")

    def xxx11(a: Int*): Unit = {
      //println(a)
      /*for (e <- a) {
        print(e)
      }*/
      a.foreach((e: Int) => {
        print(e)
      })
      println("省略类型")
      a.foreach((e) => {
        print(e)
      })
      println()
      a.foreach(e => {
        print(e)
      })
      println()
      a.foreach(e => print(e))
      println("直接传函数参数")
      a.foreach(print)
      println("当参数只使用一次时,可以用'_'替代")
      a.foreach(print(_))


    }
    //xxx11(1)
    xxx11(1, 2, 3)
    println("============高阶函数============")

    //函数作为参数
    def xxx12(x: Int, y: Int, f: (Int, Int) => Int): Unit = {
      val i = f(x, y)
      println(s"计算结果:${i}")
    }

    xxx12(1,7,(x:Int,y:Int)=>{x+y})
    xxx12(1,7,(x,y)=>{x+y})
    xxx12(1,7,(x,y)=>x+y)
    //参数按照顺序只使用一次,就可以用下滑线代替
    xxx12(1,7,_+_)
    //函数作为返回值
    def factory(i:String): (Int,Int)=>Int = {
      if("+".equals(i)){
        _+_
      }else {
        _ * _
      }
    }
    xxx12(1,7,factory("+"))
    xxx12(1,7,factory("*"))


    println("============柯里化============")
    def xxx13(x:Int)(y:Int)(z:Int): Unit ={
      println(s"${x} $y $z")
    }
    xxx13(1)(2)(3)

    println("============变量接受函数============")

    def xxx14(): Int={
      println(3)
      3
    }
    var fun = xxx14()
    println(s"fun $fun")
    var fun2 = xxx14 _
    println(s"fun $fun2")




  }


}
